const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const fs = require('fs');
const path = require('path');

const app = express();
const PORT = process.env.PORT || 3000;
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
const CONFIG_FILE = path.join(__dirname, 'config.json');
const USERS_FILE = path.join(__dirname, 'users.json');

// 中间件
app.use(cors({
  origin: true,
  credentials: true
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(session({
  secret: JWT_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: { 
    secure: false, // 生产环境设置为 true (需要 HTTPS)
    maxAge: 24 * 60 * 60 * 1000 // 24小时
  }
}));

// 读取配置文件
function readConfig() {
  try {
    const data = fs.readFileSync(CONFIG_FILE, 'utf8');
    return JSON.parse(data);
  } catch (error) {
    console.error('读取配置文件失败:', error);
    return null;
  }
}

// 写入配置文件
function writeConfig(config) {
  try {
    fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf8');
    return true;
  } catch (error) {
    console.error('写入配置文件失败:', error);
    return false;
  }
}

// 读取用户数据
function readUsers() {
  try {
    const data = fs.readFileSync(USERS_FILE, 'utf8');
    return JSON.parse(data);
  } catch (error) {
    console.error('读取用户文件失败:', error);
    return [];
  }
}

// 写入用户数据
function writeUsers(users) {
  try {
    fs.writeFileSync(USERS_FILE, JSON.stringify(users, null, 2), 'utf8');
    return true;
  } catch (error) {
    console.error('写入用户文件失败:', error);
    return false;
  }
}

// JWT 验证中间件
function authenticateToken(req, res, next) {
  const token = req.headers['authorization']?.split(' ')[1] || req.cookies.token;
  
  if (!token) {
    return res.status(401).json({
      errcode: 401,
      message: '未授权,请先登录'
    });
  }

  jwt.verify(token, JWT_SECRET, (err, user) => {
    if (err) {
      return res.status(403).json({
        errcode: 403,
        message: '令牌无效或已过期'
      });
    }
    req.user = user;
    next();
  });
}

// 管理员权限验证中间件
function requireAdmin(req, res, next) {
  if (req.user.role !== 'admin') {
    return res.status(403).json({
      errcode: 403,
      message: '需要管理员权限'
    });
  }
  next();
}

// ==================== 负载均衡逻辑 ====================

// 简单哈希函数
function simpleHash(str) {
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    const char = str.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash; // Convert to 32bit integer
  }
  return Math.abs(hash);
}

// 平均轮询 (Round Robin)
function getRoundRobinUrl(config) {
  const urls = config.loadBalancing.urls.filter(u => u.enabled);
  if (urls.length === 0) return null;

  const currentIndex = config.loadBalancing.currentIndex || 0;
  const url = urls[currentIndex % urls.length];

  // 更新索引
  config.loadBalancing.currentIndex = (currentIndex + 1) % urls.length;
  writeConfig(config);

  return url;
}

// 权重轮询 (Weighted Round Robin)
function getWeightedUrl(config) {
  const urls = config.loadBalancing.urls.filter(u => u.enabled);
  if (urls.length === 0) return null;

  const totalWeight = urls.reduce((sum, u) => sum + (u.weight || 1), 0);
  let random = Math.random() * totalWeight;

  for (let url of urls) {
    random -= (url.weight || 1);
    if (random <= 0) {
      return url;
    }
  }

  return urls[0];
}

// 随机 (Random)
function getRandomUrl(config) {
  const urls = config.loadBalancing.urls.filter(u => u.enabled);
  if (urls.length === 0) return null;

  const index = Math.floor(Math.random() * urls.length);
  return urls[index];
}

// 哈希 (Hash) - 基于客户端 IP
function getHashUrl(config, clientId) {
  const urls = config.loadBalancing.urls.filter(u => u.enabled);
  if (urls.length === 0) return null;

  const hash = simpleHash(clientId);
  const index = hash % urls.length;
  return urls[index];
}

// 根据策略获取 URL
function getUrlByStrategy(config, clientId) {
  // 如果负载均衡未启用,返回默认 URL
  if (!config.loadBalancing || !config.loadBalancing.enabled) {
    return config.webviewUrl;
  }

  const strategy = config.loadBalancing.strategy || 'round-robin';
  let selectedUrl = null;

  switch (strategy) {
    case 'round-robin':
      selectedUrl = getRoundRobinUrl(config);
      break;
    case 'weighted':
      selectedUrl = getWeightedUrl(config);
      break;
    case 'random':
      selectedUrl = getRandomUrl(config);
      break;
    case 'hash':
      selectedUrl = getHashUrl(config, clientId);
      break;
    default:
      selectedUrl = getRoundRobinUrl(config);
  }

  if (selectedUrl) {
    // 更新访问计数
    selectedUrl.accessCount = (selectedUrl.accessCount || 0) + 1;
    writeConfig(config);
    return selectedUrl.url;
  }

  // 如果没有可用的 URL,返回默认值
  return config.webviewUrl;
}

// ==================== 公开接口 ====================

// 健康检查
app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});

// 获取配置 - 公开接口
app.get('/api/config', (req, res) => {
  const config = readConfig();
  if (config) {
    // 获取客户端标识 (用于 hash 策略)
    const clientId = req.ip || req.connection.remoteAddress || 'unknown';

    // 根据负载均衡策略获取 URL
    const webviewUrl = getUrlByStrategy(config, clientId);

    // 返回配置,包含计算后的 webviewUrl
    const responseData = {
      webhost: config.webhost,
      webviewUrl: webviewUrl,
      addon_name: config.addon_name,
      version: config.version,
      updatedAt: config.updatedAt,
      updatedBy: config.updatedBy
    };

    // 如果启用了负载均衡,添加相关信息
    if (config.loadBalancing && config.loadBalancing.enabled) {
      const enabledUrls = config.loadBalancing.urls.filter(u => u.enabled);
      responseData.loadBalancing = {
        enabled: true,
        strategy: config.loadBalancing.strategy,
        totalUrls: config.loadBalancing.urls.length,
        activeUrls: enabledUrls.length
      };
    }

    res.json({
      errcode: 0,
      message: '获取配置成功',
      data: responseData
    });
  } else {
    res.status(500).json({
      errcode: 500,
      message: '读取配置失败'
    });
  }
});

// ==================== 认证接口 ====================

// 登录
app.post('/api/auth/login', async (req, res) => {
  const { username, password } = req.body;
  
  if (!username || !password) {
    return res.status(400).json({
      errcode: 400,
      message: '用户名和密码不能为空'
    });
  }

  const users = readUsers();
  const user = users.find(u => u.username === username);

  if (!user) {
    return res.status(401).json({
      errcode: 401,
      message: '用户名或密码错误'
    });
  }

  // 验证密码
  const validPassword = await bcrypt.compare(password, user.password);
  if (!validPassword) {
    return res.status(401).json({
      errcode: 401,
      message: '用户名或密码错误'
    });
  }

  // 检查用户状态
  if (user.status !== 'active') {
    return res.status(403).json({
      errcode: 403,
      message: '账户已被禁用'
    });
  }

  // 生成 JWT
  const token = jwt.sign(
    { 
      id: user.id, 
      username: user.username, 
      role: user.role 
    },
    JWT_SECRET,
    { expiresIn: '24h' }
  );

  // 更新最后登录时间
  user.lastLogin = new Date().toISOString();
  writeUsers(users);

  // 设置 cookie
  res.cookie('token', token, { 
    httpOnly: true, 
    maxAge: 24 * 60 * 60 * 1000 
  });

  res.json({
    errcode: 0,
    message: '登录成功',
    data: {
      token,
      user: {
        id: user.id,
        username: user.username,
        name: user.name,
        role: user.role,
        email: user.email
      }
    }
  });
});

// 登出
app.post('/api/auth/logout', (req, res) => {
  res.clearCookie('token');
  res.json({
    errcode: 0,
    message: '登出成功'
  });
});

// 获取当前用户信息
app.get('/api/auth/me', authenticateToken, (req, res) => {
  const users = readUsers();
  const user = users.find(u => u.id === req.user.id);
  
  if (!user) {
    return res.status(404).json({
      errcode: 404,
      message: '用户不存在'
    });
  }

  res.json({
    errcode: 0,
    message: '获取用户信息成功',
    data: {
      id: user.id,
      username: user.username,
      name: user.name,
      role: user.role,
      email: user.email,
      status: user.status,
      createdAt: user.createdAt,
      lastLogin: user.lastLogin
    }
  });
});

// ==================== 管理接口 (需要认证) ====================

// 更新配置
app.post('/api/admin/config', authenticateToken, requireAdmin, (req, res) => {
  const { webhost, webviewUrl, addon_name } = req.body;

  const currentConfig = readConfig();
  if (!currentConfig) {
    return res.status(500).json({
      errcode: 500,
      message: '读取当前配置失败'
    });
  }

  // 更新配置
  const newConfig = {
    ...currentConfig,
    webhost: webhost || currentConfig.webhost,
    webviewUrl: webviewUrl || currentConfig.webviewUrl,
    addon_name: addon_name || currentConfig.addon_name,
    version: currentConfig.version + 1,
    updatedAt: new Date().toISOString(),
    updatedBy: req.user.username
  };

  if (writeConfig(newConfig)) {
    res.json({
      errcode: 0,
      message: '配置更新成功',
      data: newConfig
    });
  } else {
    res.status(500).json({
      errcode: 500,
      message: '保存配置失败'
    });
  }
});

// 获取所有用户
app.get('/api/admin/users', authenticateToken, requireAdmin, (req, res) => {
  const users = readUsers();
  const safeUsers = users.map(u => ({
    id: u.id,
    username: u.username,
    name: u.name,
    role: u.role,
    email: u.email,
    status: u.status,
    createdAt: u.createdAt,
    lastLogin: u.lastLogin
  }));

  res.json({
    errcode: 0,
    message: '获取用户列表成功',
    data: safeUsers
  });
});

// ==================== URL 池管理接口 ====================

// 获取负载均衡配置
app.get('/api/admin/load-balancing', authenticateToken, requireAdmin, (req, res) => {
  const config = readConfig();
  if (!config) {
    return res.status(500).json({
      errcode: 500,
      message: '读取配置失败'
    });
  }

  res.json({
    errcode: 0,
    message: '获取负载均衡配置成功',
    data: config.loadBalancing || {
      enabled: false,
      strategy: 'round-robin',
      currentIndex: 0,
      urls: []
    }
  });
});

// 更新负载均衡策略
app.post('/api/admin/load-balancing/strategy', authenticateToken, requireAdmin, (req, res) => {
  const { enabled, strategy } = req.body;

  const config = readConfig();
  if (!config) {
    return res.status(500).json({
      errcode: 500,
      message: '读取配置失败'
    });
  }

  if (!config.loadBalancing) {
    config.loadBalancing = {
      enabled: false,
      strategy: 'round-robin',
      currentIndex: 0,
      urls: []
    };
  }

  if (enabled !== undefined) {
    config.loadBalancing.enabled = enabled;
  }

  if (strategy) {
    const validStrategies = ['round-robin', 'weighted', 'random', 'hash'];
    if (!validStrategies.includes(strategy)) {
      return res.status(400).json({
        errcode: 400,
        message: '无效的轮询策略'
      });
    }
    config.loadBalancing.strategy = strategy;
    config.loadBalancing.currentIndex = 0; // 重置索引
  }

  config.version = config.version + 1;
  config.updatedAt = new Date().toISOString();
  config.updatedBy = req.user.username;

  if (writeConfig(config)) {
    res.json({
      errcode: 0,
      message: '更新策略成功',
      data: config.loadBalancing
    });
  } else {
    res.status(500).json({
      errcode: 500,
      message: '保存配置失败'
    });
  }
});

// 添加 URL
app.post('/api/admin/urls', authenticateToken, requireAdmin, (req, res) => {
  const { name, url, weight, description, enabled } = req.body;

  if (!name || !url) {
    return res.status(400).json({
      errcode: 400,
      message: '名称和 URL 不能为空'
    });
  }

  const config = readConfig();
  if (!config) {
    return res.status(500).json({
      errcode: 500,
      message: '读取配置失败'
    });
  }

  if (!config.loadBalancing) {
    config.loadBalancing = {
      enabled: false,
      strategy: 'round-robin',
      currentIndex: 0,
      urls: []
    };
  }

  // 生成新 ID
  const maxId = config.loadBalancing.urls.length > 0
    ? Math.max(...config.loadBalancing.urls.map(u => u.id))
    : 0;

  const newUrl = {
    id: maxId + 1,
    name,
    url,
    weight: weight || 1,
    enabled: enabled !== undefined ? enabled : true,
    description: description || '',
    accessCount: 0,
    createdAt: new Date().toISOString()
  };

  config.loadBalancing.urls.push(newUrl);
  config.version = config.version + 1;
  config.updatedAt = new Date().toISOString();
  config.updatedBy = req.user.username;

  if (writeConfig(config)) {
    res.json({
      errcode: 0,
      message: '添加 URL 成功',
      data: newUrl
    });
  } else {
    res.status(500).json({
      errcode: 500,
      message: '保存配置失败'
    });
  }
});

// 更新 URL
app.put('/api/admin/urls/:id', authenticateToken, requireAdmin, (req, res) => {
  const urlId = parseInt(req.params.id);
  const { name, url, weight, description, enabled } = req.body;

  const config = readConfig();
  if (!config || !config.loadBalancing) {
    return res.status(500).json({
      errcode: 500,
      message: '读取配置失败'
    });
  }

  const urlIndex = config.loadBalancing.urls.findIndex(u => u.id === urlId);
  if (urlIndex === -1) {
    return res.status(404).json({
      errcode: 404,
      message: 'URL 不存在'
    });
  }

  // 更新字段
  if (name) config.loadBalancing.urls[urlIndex].name = name;
  if (url) config.loadBalancing.urls[urlIndex].url = url;
  if (weight !== undefined) config.loadBalancing.urls[urlIndex].weight = weight;
  if (description !== undefined) config.loadBalancing.urls[urlIndex].description = description;
  if (enabled !== undefined) config.loadBalancing.urls[urlIndex].enabled = enabled;

  config.loadBalancing.urls[urlIndex].updatedAt = new Date().toISOString();
  config.version = config.version + 1;
  config.updatedAt = new Date().toISOString();
  config.updatedBy = req.user.username;

  if (writeConfig(config)) {
    res.json({
      errcode: 0,
      message: '更新 URL 成功',
      data: config.loadBalancing.urls[urlIndex]
    });
  } else {
    res.status(500).json({
      errcode: 500,
      message: '保存配置失败'
    });
  }
});

// 删除 URL
app.delete('/api/admin/urls/:id', authenticateToken, requireAdmin, (req, res) => {
  const urlId = parseInt(req.params.id);

  const config = readConfig();
  if (!config || !config.loadBalancing) {
    return res.status(500).json({
      errcode: 500,
      message: '读取配置失败'
    });
  }

  const urlIndex = config.loadBalancing.urls.findIndex(u => u.id === urlId);
  if (urlIndex === -1) {
    return res.status(404).json({
      errcode: 404,
      message: 'URL 不存在'
    });
  }

  config.loadBalancing.urls.splice(urlIndex, 1);
  config.version = config.version + 1;
  config.updatedAt = new Date().toISOString();
  config.updatedBy = req.user.username;

  if (writeConfig(config)) {
    res.json({
      errcode: 0,
      message: '删除 URL 成功'
    });
  } else {
    res.status(500).json({
      errcode: 500,
      message: '保存配置失败'
    });
  }
});

// 启动服务器
app.listen(PORT, () => {
  console.log(`\n========================================`);
  console.log(`  配置管理系统 v2.0 (负载均衡版)`);
  console.log(`========================================`);
  console.log(`  服务器运行在端口: ${PORT}`);
  console.log(`  访问地址: http://localhost:${PORT}`);
  console.log(`========================================`);
  console.log(`\n公开接口:`);
  console.log(`  GET  /api/config          - 获取配置 (支持负载均衡)`);
  console.log(`  GET  /health              - 健康检查`);
  console.log(`\n认证接口:`);
  console.log(`  POST /api/auth/login      - 登录`);
  console.log(`  POST /api/auth/logout     - 登出`);
  console.log(`  GET  /api/auth/me         - 获取当前用户`);
  console.log(`\n管理接口 (需要认证):`);
  console.log(`  POST /api/admin/config    - 更新配置`);
  console.log(`  GET  /api/admin/users     - 获取用户列表`);
  console.log(`\n负载均衡接口 (需要管理员权限):`);
  console.log(`  GET    /api/admin/load-balancing          - 获取负载均衡配置`);
  console.log(`  POST   /api/admin/load-balancing/strategy - 更新轮询策略`);
  console.log(`  POST   /api/admin/urls                    - 添加 URL`);
  console.log(`  PUT    /api/admin/urls/:id                - 更新 URL`);
  console.log(`  DELETE /api/admin/urls/:id                - 删除 URL`);
  console.log(`========================================`);
  console.log(`\n支持的轮询策略:`);
  console.log(`  round-robin  - 平均轮询`);
  console.log(`  weighted     - 权重轮询`);
  console.log(`  random       - 随机选择`);
  console.log(`  hash         - 哈希分配 (基于客户端IP)`);
  console.log(`========================================`);
  console.log(`\n默认管理员账号:`);
  console.log(`  用户名: admin`);
  console.log(`  密码: admin123`);
  console.log(`========================================\n`);
});

